package com.jprocms.module.cms.service.guestbook;

import com.jpro.framework.common.pojo.PageResult;
import com.jpro.framework.common.util.object.BeanUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.page.PageMethod;
import com.jprocms.module.cms.controller.admin.guestbook.vo.GuestbookCreateReqVO;
import com.jprocms.module.cms.controller.admin.guestbook.vo.GuestbookPageReqVO;
import com.jprocms.module.cms.controller.admin.guestbook.vo.GuestbookQueryListReqVO;
import com.jprocms.module.cms.controller.admin.guestbook.vo.GuestbookUpdateReqVO;
import com.jprocms.module.cms.convert.PageConverter;
import com.jprocms.module.cms.convert.guestbook.GuestbookConvert;
import com.jprocms.module.cms.dal.dataobject.guestbook.GuestbookDO;
import com.jprocms.module.cms.dal.mysql.guestbook.GuestbookMapper;
import com.jprocms.module.cms.util.CmsContextUtil;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;

import static com.jpro.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.jprocms.module.cms.enums.ErrorCodeConstants.GUESTBOOK_NOT_EXISTS;
import static com.jprocms.module.cms.enums.LogRecordConstants.*;

/**
 * 留言板 Service 实现类
 *
 * @author jprocms
 */
@Service
@Validated
public class GuestbookServiceImpl extends ServiceImpl<GuestbookMapper, GuestbookDO> implements GuestbookService {

    @Resource
    private GuestbookMapper guestbookMapper;
    @Resource
    private PageConverter pageConverter;

    @Override
    @LogRecord(type = CMS_GUESTBOOK_TYPE, subType = CMS_GUESTBOOK_CREATE_SUB_TYPE, bizNo = "{{#guestbook.id}}", success = CMS_GUESTBOOK_CREATE_SUCCESS)
    @Transactional(rollbackFor = Exception.class)
    public Long createGuestbook(GuestbookCreateReqVO createReqVO) {
        // 插入
        GuestbookDO guestbook = GuestbookConvert.INSTANCE.convert(createReqVO);
        guestbookMapper.insert(guestbook);
        // 记录操作日志上下文
        LogRecordContext.putVariable("guestbook", guestbook);
        // 返回
        return guestbook.getId();
    }

    @Override
    @LogRecord(type = CMS_GUESTBOOK_TYPE, subType = CMS_GUESTBOOK_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CMS_GUESTBOOK_UPDATE_SUCCESS)
    @Transactional(rollbackFor = Exception.class)
    public void updateGuestbook(GuestbookUpdateReqVO updateReqVO) {
        // 校验存在
        GuestbookDO oldGuestbook = validateGuestbookExists(updateReqVO.getId());
        // 更新
        GuestbookDO updateObj = GuestbookConvert.INSTANCE.convert(updateReqVO);
        guestbookMapper.updateById(updateObj);
        // 记录操作日志上下文
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldGuestbook, GuestbookUpdateReqVO.class));
        LogRecordContext.putVariable("guestbook", updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGuestbookBatch(Collection<GuestbookDO> updateDOs) {
        guestbookMapper.updateBatch(updateDOs);
    }

    @Override
    @LogRecord(type = CMS_GUESTBOOK_TYPE, subType = CMS_GUESTBOOK_DELETE_SUB_TYPE, bizNo = "{{#id}}", success = CMS_GUESTBOOK_DELETE_SUCCESS)
    @Transactional(rollbackFor = Exception.class)
    public void deleteGuestbook(Long id) {
        // 校验存在
        GuestbookDO guestbook = validateGuestbookExists(id);
        // 删除
        guestbookMapper.deleteById(id);
        // 记录操作日志上下文
        LogRecordContext.putVariable("guestbook", guestbook);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteGuestbooks(Collection<Long> ids) {
        guestbookMapper.deleteBatchIds(ids);
    }

    private GuestbookDO validateGuestbookExists(Long id) {
        final GuestbookDO guestbookDO = guestbookMapper.selectById(id);
        if (guestbookDO == null) {
            throw exception(GUESTBOOK_NOT_EXISTS);
        }
        return guestbookDO;
    }

    @Override
    public GuestbookDO getGuestbook(Long id) {
        return guestbookMapper.selectById(id);
    }

    @Override
    public List<GuestbookDO> getGuestbookList(Collection<Long> ids) {
        return guestbookMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<GuestbookDO> getGuestbookPage(GuestbookPageReqVO pageReqVO) {
        pageReqVO = assembleParams(pageReqVO);
        final IPage<GuestbookDO> guestbookDOIPage = guestbookMapper.selectPage(pageReqVO, pageReqVO.getOrderItems(), new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()));
        return pageConverter.page(guestbookDOIPage);
    }

    @Override
    public Long getGuestbookCount(Long siteId, Integer status) {
        LambdaQueryWrapper<GuestbookDO> wrapper = new LambdaQueryWrapper();
        wrapper.eq(GuestbookDO::getSiteId, siteId);
        wrapper.eq(GuestbookDO::getStatus, status);
        return guestbookMapper.selectCount(wrapper);
    }

    @Override
    public List<GuestbookDO> getGuestbookList(GuestbookQueryListReqVO reqVO) {
        GuestbookQueryListReqVO reqListVO = (GuestbookQueryListReqVO) assembleParams(reqVO);
        return PageMethod.offsetPage(reqVO.getOffset(), reqVO.getCount(), false).doSelectPage(() -> guestbookMapper.selectList(reqListVO, reqListVO.getOrderItems()));
    }

    private GuestbookPageReqVO assembleParams(GuestbookPageReqVO pageReqVO) {
        if (pageReqVO.getSiteId() == null) {
            pageReqVO.setSiteId(CmsContextUtil.getCurrSiteId());
        }
        if (pageReqVO.getCreateTime() != null) {
            if (pageReqVO.getCreateTime().length > 0 && pageReqVO.getCreateTime()[0] != null) {
                pageReqVO.setCreateTimeBegin(pageReqVO.getCreateTime()[0]);
            }
            if (pageReqVO.getCreateTime().length > 1 && pageReqVO.getCreateTime()[1] != null) {
                pageReqVO.setCreateTimeEnd(pageReqVO.getCreateTime()[1]);
            }
        }
        if (pageReqVO.getReplyDate() != null) {
            if (pageReqVO.getReplyDate().length > 0 && pageReqVO.getReplyDate()[0] != null) {
                pageReqVO.setReplyDateBegin(pageReqVO.getReplyDate()[0]);
            }
            if (pageReqVO.getReplyDate().length > 1 && pageReqVO.getReplyDate()[1] != null) {
                pageReqVO.setReplyDateEnd(pageReqVO.getReplyDate()[1]);
            }
        }
        return pageReqVO;
    }


}
